"""
LLM客户端模块

提供与各种LLM模型的统一接口
"""

import os
import openai
from typing import List, Dict, Any, Optional
import logging
import backoff
from datetime import datetime
import json

# 导入专业提示词配置
try:
    from ..config.sentiment_prompts import SentimentPrompts
except ImportError:
    # 如果导入失败，提供一个简单的备用实现
    class SentimentPrompts:
        @staticmethod
        def get_professional_a_share_system_prompt():
            return "你是一个专业的A股市场分析师，擅长解读新闻对股票走势的影响。"

logger = logging.getLogger(__name__)


class LLMClient:
    """LLM客户端类，支持多种模型"""
    
    def __init__(self):
        """初始化LLM客户端"""
        self.openai_api_key = os.getenv("OPENAI_API_KEY")
        self.openai_model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")

        # DeepSeek配置（优先使用）
        self.deepseek_api_key = os.getenv("DEEPSEEK_API_KEY")
        self.deepseek_model = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
        self.deepseek_base_url = "https://api.deepseek.com/v1"

        # OpenAI兼容API配置
        self.openai_compatible_api_key = os.getenv("OPENAI_COMPATIBLE_API_KEY")
        self.openai_compatible_base_url = os.getenv("OPENAI_COMPATIBLE_BASE_URL")
        self.openai_compatible_model = os.getenv("OPENAI_COMPATIBLE_MODEL")

        # Gemini配置
        self.gemini_api_key = os.getenv("GEMINI_API_KEY")
        self.gemini_model = os.getenv("GEMINI_MODEL", "gemini-1.5-flash")

        # 测试模式配置
        self.test_mode = os.getenv("TEST_MODE", "false").lower() == "true"

        # 初始化客户端
        self.openai_client = None
        self.deepseek_client = None
        self.openai_compatible_client = None

        # 检查是否有有效的API密钥
        has_valid_key = False

        # 优先初始化DeepSeek客户端
        if self.deepseek_api_key and self.deepseek_api_key != "your-deepseek-api-key":
            try:
                self.deepseek_client = openai.OpenAI(
                    api_key=self.deepseek_api_key,
                    base_url=self.deepseek_base_url
                )
                logger.info("DeepSeek客户端初始化完成")
                has_valid_key = True
            except Exception as e:
                logger.warning(f"DeepSeek客户端初始化失败: {e}")

        if self.openai_api_key and self.openai_api_key != "your-openai-api-key":
            try:
                self.openai_client = openai.OpenAI(api_key=self.openai_api_key)
                logger.info("OpenAI客户端初始化完成")
                has_valid_key = True
            except Exception as e:
                logger.warning(f"OpenAI客户端初始化失败: {e}")

        if (self.openai_compatible_api_key and self.openai_compatible_api_key != "your-openai-compatible-api-key"
            and self.openai_compatible_base_url and self.openai_compatible_base_url != "https://your-api-endpoint.com/v1"):
            try:
                self.openai_compatible_client = openai.OpenAI(
                    api_key=self.openai_compatible_api_key,
                    base_url=self.openai_compatible_base_url
                )
                logger.info("OpenAI兼容客户端初始化完成")
                has_valid_key = True
            except Exception as e:
                logger.warning(f"OpenAI兼容客户端初始化失败: {e}")

        # 如果没有有效的API密钥，启用测试模式
        if not has_valid_key:
            self.test_mode = True
            logger.warning("未检测到有效的API密钥，启用测试模式")

        logger.info("LLM客户端初始化完成")
    
    @backoff.on_exception(backoff.expo, Exception, max_tries=3)
    def chat_completion(
        self,
        messages: List[Dict[str, str]],
        model: Optional[str] = None,
        temperature: float = 0.7,
        max_tokens: Optional[int] = None,
        provider: str = "auto"
    ) -> str:
        """
        聊天完成接口

        Args:
            messages: 消息列表
            model: 模型名称
            temperature: 温度参数
            max_tokens: 最大token数
            provider: 提供商 ("deepseek", "openai", "openai_compatible", "gemini", "auto")

        Returns:
            str: 模型回复
        """
        try:
            # 如果是测试模式，返回模拟响应
            if self.test_mode:
                return self._get_test_response(messages)

            if provider == "deepseek" and self.deepseek_client:
                return self._deepseek_chat_completion(
                    messages, model or self.deepseek_model, temperature, max_tokens
                )
            elif provider == "openai" and self.openai_client:
                return self._openai_chat_completion(
                    messages, model or self.openai_model, temperature, max_tokens
                )
            elif provider == "openai_compatible" and self.openai_compatible_client:
                return self._openai_compatible_chat_completion(
                    messages, model or self.openai_compatible_model, temperature, max_tokens
                )
            elif provider == "gemini" and self.gemini_api_key:
                return self._gemini_chat_completion(
                    messages, model or self.gemini_model, temperature, max_tokens
                )
            else:
                # 自动选择可用的提供商（优先DeepSeek）
                if self.deepseek_client:
                    return self._deepseek_chat_completion(
                        messages, self.deepseek_model, temperature, max_tokens
                    )
                elif self.openai_client:
                    return self._openai_chat_completion(
                        messages, self.openai_model, temperature, max_tokens
                    )
                elif self.openai_compatible_client:
                    return self._openai_compatible_chat_completion(
                        messages, self.openai_compatible_model, temperature, max_tokens
                    )
                else:
                    # 如果没有可用的提供商，使用测试模式
                    logger.warning("没有可用的LLM提供商，使用测试模式")
                    return self._get_test_response(messages)

        except Exception as e:
            logger.error(f"LLM调用失败: {e}")
            # 在API调用失败时，也可以回退到测试模式
            if self.test_mode:
                logger.warning("API调用失败，使用测试响应")
                return self._get_test_response(messages)
            raise
    
    def _deepseek_chat_completion(
        self,
        messages: List[Dict[str, str]],
        model: str,
        temperature: float,
        max_tokens: Optional[int]
    ) -> str:
        """DeepSeek聊天完成"""
        try:
            response = self.deepseek_client.chat.completions.create(
                model=model,
                messages=messages,
                temperature=temperature,
                max_tokens=max_tokens
            )
            return response.choices[0].message.content
        except Exception as e:
            logger.error(f"DeepSeek API调用失败: {e}")
            raise

    def _openai_chat_completion(
        self,
        messages: List[Dict[str, str]],
        model: str,
        temperature: float,
        max_tokens: Optional[int]
    ) -> str:
        """OpenAI聊天完成"""
        try:
            response = self.openai_client.chat.completions.create(
                model=model,
                messages=messages,
                temperature=temperature,
                max_tokens=max_tokens
            )
            return response.choices[0].message.content
        except Exception as e:
            logger.error(f"OpenAI API调用失败: {e}")
            raise
    
    def _openai_compatible_chat_completion(
        self,
        messages: List[Dict[str, str]],
        model: str,
        temperature: float,
        max_tokens: Optional[int]
    ) -> str:
        """OpenAI兼容API聊天完成"""
        try:
            response = self.openai_compatible_client.chat.completions.create(
                model=model,
                messages=messages,
                temperature=temperature,
                max_tokens=max_tokens
            )
            return response.choices[0].message.content
        except Exception as e:
            logger.error(f"OpenAI兼容API调用失败: {e}")
            raise
    
    def _gemini_chat_completion(
        self,
        messages: List[Dict[str, str]],
        model: str,
        temperature: float,
        max_tokens: Optional[int]
    ) -> str:
        """Gemini聊天完成"""
        try:
            # 这里需要实现Gemini API调用
            # 由于Gemini API可能有不同的接口格式，这里提供一个占位符实现
            logger.warning("Gemini API调用尚未实现")
            return "Gemini API调用尚未实现"
        except Exception as e:
            logger.error(f"Gemini API调用失败: {e}")
            raise

    def _get_test_response(self, messages: List[Dict[str, str]]) -> str:
        """获取测试模式响应"""
        try:
            # 分析用户消息内容，提供相应的模拟响应
            user_message = ""
            for msg in messages:
                if msg.get("role") == "user":
                    user_message = msg.get("content", "").lower()
                    break

            # 根据消息内容返回不同的模拟响应
            if "技术分析" in user_message or "technical" in user_message:
                return """基于技术分析（测试模式）：

**技术指标分析**
- MA5: 当前价格位于5日均线上方，短期趋势向上
- MACD: 金叉信号，动能转强
- RSI: 55，处于中性偏强区域
- 成交量: 近期放量上涨，资金关注度提升

**技术结论**
- 短期趋势: 看涨
- 支撑位: 建议关注前期低点
- 阻力位: 关注前期高点压力
- 操作建议: 可考虑逢低买入，设置止损

注意：这是测试模式响应，实际投资请谨慎决策。"""

            elif "基本面" in user_message or "fundamental" in user_message:
                return """基于基本面分析（测试模式）：

**财务指标评估**
- 营收增长: 同比增长稳定
- 净利润率: 维持在合理水平
- ROE: 股东回报率表现良好
- 负债率: 财务结构健康

**行业地位**
- 市场份额: 在细分领域具有竞争优势
- 技术壁垒: 拥有一定的技术护城河
- 管理团队: 经验丰富，执行力强

**投资价值**
- 估值水平: 相对合理
- 成长性: 具备中长期增长潜力
- 风险因素: 需关注行业政策变化

注意：这是测试模式响应，实际投资请谨慎决策。"""

            elif "情绪" in user_message or "sentiment" in user_message:
                return """市场情绪分析（测试模式）：

**新闻情感分析**
- 整体情绪: 中性偏积极
- 正面新闻比例: 60%
- 关键主题: 业绩增长、政策利好、技术创新

**市场表现**
- 资金流向: 近期有资金净流入
- 机构关注: 多家机构给予关注评级
- 散户情绪: 整体保持谨慎乐观

**情绪结论**
- 市场信心: 逐步恢复
- 投资者预期: 对未来发展持乐观态度
- 风险提示: 注意市场波动风险

注意：这是测试模式响应，实际投资请谨慎决策。"""

            elif "估值" in user_message or "valuation" in user_message:
                return """估值分析（测试模式）：

**估值方法**
- PE估值: 当前PE相对合理
- PB估值: 账面价值支撑良好
- DCF估值: 现金流折现显示内在价值
- 相对估值: 与同行业对比具有优势

**价值评估**
- 内在价值: 略高于当前市价
- 安全边际: 存在一定安全边际
- 目标价格: 建议关注合理价格区间

**投资建议**
- 投资价值: 具备中长期投资价值
- 买入时机: 可考虑分批建仓
- 风险控制: 设置合理止损位

注意：这是测试模式响应，实际投资请谨慎决策。"""

            else:
                return """综合投资分析（测试模式）：

**综合评估**
基于多维度分析，该股票在技术面、基本面、市场情绪等方面表现如下：

**主要优势**
- 基本面稳健，财务指标良好
- 技术面显示积极信号
- 市场情绪逐步改善
- 估值水平相对合理

**风险因素**
- 市场整体波动风险
- 行业政策变化风险
- 宏观经济环境影响

**投资建议**
- 适合中长期投资者关注
- 建议分批建仓，控制风险
- 密切关注基本面变化

重要提示：这是测试模式的模拟响应，仅供系统测试使用。
实际投资决策请基于真实的市场数据和专业分析。"""

        except Exception as e:
            logger.error(f"生成测试响应失败: {e}")
            return "测试模式响应生成失败，请检查系统配置。"

    def analyze_with_llm(
        self,
        prompt: str,
        context_data: Dict[str, Any],
        analysis_type: str = "general"
    ) -> str:
        """
        使用LLM进行分析
        
        Args:
            prompt: 分析提示
            context_data: 上下文数据
            analysis_type: 分析类型
            
        Returns:
            str: 分析结果
        """
        try:
            # 构建系统消息
            system_message = self._build_system_message(analysis_type)
            
            # 构建用户消息
            user_message = self._build_user_message(prompt, context_data)
            
            messages = [
                {"role": "system", "content": system_message},
                {"role": "user", "content": user_message}
            ]
            
            # 调用LLM
            response = self.chat_completion(messages, temperature=0.3)
            
            logger.info(f"LLM分析完成，类型: {analysis_type}")
            return response
            
        except Exception as e:
            logger.error(f"LLM分析失败: {e}")
            return f"分析失败: {str(e)}"
    
    def _build_system_message(self, analysis_type: str) -> str:
        """构建系统消息"""
        base_prompt = """你是一个专业的投资分析师，具有丰富的A股市场经验。
请基于提供的数据进行客观、专业的分析，并给出明确的投资建议。

分析要求：
1. 基于事实和数据进行分析
2. 考虑多个维度的因素
3. 给出明确的结论和建议
4. 说明分析的逻辑和依据
5. 评估风险和不确定性

请用中文回答。"""
        
        if analysis_type == "technical":
            return base_prompt + "\n\n你专注于技术分析，包括价格趋势、技术指标、图表模式等。"
        elif analysis_type == "fundamental":
            return base_prompt + "\n\n你专注于基本面分析，包括财务指标、行业分析、公司价值等。"
        elif analysis_type == "sentiment":
            return base_prompt + "\n\n你专注于市场情绪分析，包括新闻情感、投资者情绪、市场氛围等。"
        elif analysis_type == "risk":
            return base_prompt + "\n\n你专注于风险管理，包括风险评估、仓位管理、止损策略等。"
        elif analysis_type == "debate":
            return base_prompt + "\n\n你是一个中立的第三方评估者，需要客观评估多空双方的观点。"
        else:
            return base_prompt
    
    def _build_user_message(self, prompt: str, context_data: Dict[str, Any]) -> str:
        """构建用户消息"""
        message = f"分析任务: {prompt}\n\n"
        
        # 添加上下文数据
        if context_data:
            message += "相关数据:\n"
            for key, value in context_data.items():
                if isinstance(value, (dict, list)):
                    message += f"{key}: {str(value)}...\n" # 无限制长度 
                else:
                    message += f"{key}: {value}\n"
        
        message += "\n请进行详细分析并给出结论。"
        return message
    
    def evaluate_debate(
        self,
        bull_analysis: str,
        bear_analysis: str,
        market_data: Dict[str, Any]
    ) -> Dict[str, Any]:
        """
        评估辩论结果
        
        Args:
            bull_analysis: 多方分析
            bear_analysis: 空方分析
            market_data: 市场数据
            
        Returns:
            Dict[str, Any]: 评估结果
        """
        try:
            prompt = """请作为中立的第三方评估者，客观评估以下多空双方的投资观点：

多方观点：
{bull_analysis}

空方观点：
{bear_analysis}

请从以下维度进行评估：
1. 论据的充分性和说服力
2. 逻辑的严密性
3. 对风险的考虑
4. 结论的合理性

最后给出：
- 哪一方的观点更有说服力（多方/空方/平分秋色）
- 综合评分（0-10分）
- 主要理由
- 投资建议

请用JSON格式回答，包含以下字段：
- winner: "bull" | "bear" | "tie"
- bull_score: 0-10
- bear_score: 0-10
- reasoning: 评估理由
- recommendation: 投资建议
""".format(bull_analysis=bull_analysis, bear_analysis=bear_analysis)
            
            context_data = {"market_data": market_data}
            response = self.analyze_with_llm(prompt, context_data, "debate")
            
            # 尝试解析JSON响应
            try:
                import json
                result = json.loads(response)
                return result
            except:
                # 如果JSON解析失败，返回文本结果
                return {
                    "winner": "tie",
                    "bull_score": 5.0,
                    "bear_score": 5.0,
                    "reasoning": response,
                    "recommendation": "建议谨慎投资"
                }
                
        except Exception as e:
            logger.error(f"辩论评估失败: {e}")
            return {
                "winner": "tie",
                "bull_score": 5.0,
                "bear_score": 5.0,
                "reasoning": f"评估失败: {str(e)}",
                "recommendation": "建议谨慎投资"
            }

    def analyze_a_share_sentiment(
        self,
        news_data: List[Dict[str, Any]],
        ticker: str = "",
        analysis_mode: str = "standard"
    ) -> Dict[str, Any]:
        """
        专业A股情感分析

        Args:
            news_data: 新闻数据列表
            ticker: 股票代码
            analysis_mode: 分析模式 ("standard", "detailed", "quick")

        Returns:
            Dict[str, Any]: 情感分析结果
        """
        try:
            # 构建专业A股分析系统提示词
            system_prompt = SentimentPrompts.get_professional_a_share_system_prompt()

            # 构建新闻内容摘要
            news_summary = self._build_news_summary(news_data, ticker)

            # 根据分析模式调整提示词
            if analysis_mode == "detailed":
                user_prompt = f"""请对以下关于股票 {ticker} 的新闻进行详细的A股市场情感分析：

{news_summary}

请按照专业A股分析框架，提供以下信息：
1. 整体情感分数（-1到1之间，保留2位小数）
2. 情感分类（极其积极/积极/轻微积极/中性/轻微消极/消极/极其消极）
3. 置信度（0-1之间，保留2位小数）
4. 主要情感驱动因素（最多5个）
5. 正面新闻比例（百分比）
6. 关键主题识别（最多5个）
7. A股市场特殊性分析
8. 投资建议和风险提示

请用JSON格式回答，包含以下字段：
{{
    "sentiment_score": 数值,
    "sentiment_category": "分类",
    "confidence": 数值,
    "driving_factors": ["因素1", "因素2", ...],
    "positive_ratio": 数值,
    "key_themes": ["主题1", "主题2", ...],
    "a_share_analysis": "A股特殊性分析",
    "investment_advice": "投资建议",
    "risk_warning": "风险提示"
}}"""
            elif analysis_mode == "quick":
                user_prompt = f"""请对以下关于股票 {ticker} 的新闻进行快速情感分析：

{news_summary}

请提供：
1. 情感分数（-1到1之间）
2. 情感分类
3. 简要分析

请用JSON格式回答：
{{
    "sentiment_score": 数值,
    "sentiment_category": "分类",
    "brief_analysis": "简要分析"
}}"""
            else:  # standard
                user_prompt = f"""请对以下关于股票 {ticker} 的新闻进行标准情感分析：

{news_summary}

请按照A股分析标准，提供：
1. 情感分数（-1到1之间）
2. 情感分类
3. 置信度
4. 主要驱动因素
5. 投资建议

请用JSON格式回答：
{{
    "sentiment_score": 数值,
    "sentiment_category": "分类",
    "confidence": 数值,
    "driving_factors": ["因素1", "因素2", ...],
    "investment_advice": "投资建议"
}}"""

            messages = [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_prompt}
            ]

            # 调用LLM进行分析
            response = self.chat_completion(messages, temperature=0.2)

            # 尝试解析JSON响应
            try:
                result = json.loads(response)

                # 验证和标准化结果
                result = self._validate_sentiment_result(result, analysis_mode)

                logger.info(f"A股情感分析完成，股票: {ticker}, 模式: {analysis_mode}")
                return result

            except json.JSONDecodeError:
                # 如果JSON解析失败，返回基础结果
                logger.warning("LLM响应JSON解析失败，返回基础结果")
                return self._create_fallback_sentiment_result(response, analysis_mode)

        except Exception as e:
            logger.error(f"A股情感分析失败: {e}")
            return self._create_error_sentiment_result(str(e), analysis_mode)

    def _build_news_summary(self, news_data: List[Dict[str, Any]], ticker: str) -> str:
        """构建新闻摘要"""
        if not news_data:
            return f"未找到关于股票 {ticker} 的相关新闻。"

        summary = f"关于股票 {ticker} 的新闻摘要（共 {len(news_data)} 条）：\n\n"

        for i, news in enumerate(news_data[:10], 1):  # 最多处理10条新闻
            title = news.get('title', '无标题')
            content = news.get('content', news.get('summary', ''))
            publish_time = news.get('publish_time', news.get('date', ''))

            # 限制内容长度
            if len(content) > 200:
                content = content[:200] + "..."

            summary += f"{i}. 【{publish_time}】{title}\n"
            if content:
                summary += f"   内容: {content}\n"
            summary += "\n"

        return summary

    def _validate_sentiment_result(self, result: Dict[str, Any], analysis_mode: str) -> Dict[str, Any]:
        """验证和标准化情感分析结果"""
        # 确保必要字段存在
        if "sentiment_score" not in result:
            result["sentiment_score"] = 0.0

        # 确保分数在有效范围内
        score = float(result["sentiment_score"])
        result["sentiment_score"] = max(-1.0, min(1.0, score))

        # 确保情感分类存在
        if "sentiment_category" not in result:
            score = result["sentiment_score"]
            if score >= 0.8:
                result["sentiment_category"] = "极其积极"
            elif score >= 0.5:
                result["sentiment_category"] = "积极"
            elif score >= 0.1:
                result["sentiment_category"] = "轻微积极"
            elif score >= -0.1:
                result["sentiment_category"] = "中性"
            elif score >= -0.5:
                result["sentiment_category"] = "轻微消极"
            elif score >= -0.8:
                result["sentiment_category"] = "消极"
            else:
                result["sentiment_category"] = "极其消极"

        # 根据分析模式确保必要字段
        if analysis_mode == "detailed":
            defaults = {
                "confidence": 0.7,
                "driving_factors": ["数据不足"],
                "positive_ratio": 50.0,
                "key_themes": ["暂无主题"],
                "a_share_analysis": "需要更多数据进行A股特殊性分析",
                "investment_advice": "建议谨慎投资",
                "risk_warning": "投资有风险，入市需谨慎"
            }
        elif analysis_mode == "quick":
            defaults = {
                "brief_analysis": "基于有限数据的快速分析"
            }
        else:  # standard
            defaults = {
                "confidence": 0.7,
                "driving_factors": ["数据不足"],
                "investment_advice": "建议谨慎投资"
            }

        for key, default_value in defaults.items():
            if key not in result:
                result[key] = default_value

        return result

    def _create_fallback_sentiment_result(self, response: str, analysis_mode: str) -> Dict[str, Any]:
        """创建备用情感分析结果"""
        base_result = {
            "sentiment_score": 0.0,
            "sentiment_category": "中性",
            "raw_response": response
        }

        if analysis_mode == "detailed":
            base_result.update({
                "confidence": 0.5,
                "driving_factors": ["LLM响应解析失败"],
                "positive_ratio": 50.0,
                "key_themes": ["解析错误"],
                "a_share_analysis": "响应解析失败，无法进行详细分析",
                "investment_advice": "建议谨慎投资",
                "risk_warning": "数据解析异常，投资需谨慎"
            })
        elif analysis_mode == "quick":
            base_result.update({
                "brief_analysis": "响应解析失败，无法提供详细分析"
            })
        else:  # standard
            base_result.update({
                "confidence": 0.5,
                "driving_factors": ["响应解析失败"],
                "investment_advice": "建议谨慎投资"
            })

        return base_result

    def _create_error_sentiment_result(self, error_msg: str, analysis_mode: str) -> Dict[str, Any]:
        """创建错误情感分析结果"""
        base_result = {
            "sentiment_score": 0.0,
            "sentiment_category": "中性",
            "error": error_msg
        }

        if analysis_mode == "detailed":
            base_result.update({
                "confidence": 0.0,
                "driving_factors": ["分析失败"],
                "positive_ratio": 50.0,
                "key_themes": ["错误"],
                "a_share_analysis": f"分析失败: {error_msg}",
                "investment_advice": "建议暂停投资决策",
                "risk_warning": "系统分析异常，请谨慎投资"
            })
        elif analysis_mode == "quick":
            base_result.update({
                "brief_analysis": f"快速分析失败: {error_msg}"
            })
        else:  # standard
            base_result.update({
                "confidence": 0.0,
                "driving_factors": ["分析失败"],
                "investment_advice": "建议暂停投资决策"
            })

        return base_result
